//
//  JPNetworkingDefines.h
//  JPWords
//
//  Created by 梁淑婷 on 2024/4/20.
//

#ifndef JPNetworkingDefines_h
#define JPNetworkingDefines_h

#import <UIKit/UIKit.h>

@class JPAPIBaseManager;
@class JPURLResponse;


typedef NS_ENUM(NSUInteger,JPServiceAPIEnvironment) {
   JPServiceAPIEnvironmentDevelop,
   JPServiceAPIEnvironmentReleaseCandidate,
   JPServiceAPIEnvironmentRelease
};

typedef NS_ENUM(NSUInteger,JPAPIManagerRequestType){
   JPAPIManagerRequestTypePOST,
   JPAPIManagerRequestTypeGET,
   JPAPIManagerRequestTypeAppendGET,
   JPAPIManagerRequestTypeAppendPOST,
   JPAPIManagerRequestTypePOSTFile,
   JPAPIManagerRequestTypeAppendParameterPOST,
   JPAPIManagerRequestTypeDELETE
};

typedef NS_ENUM (NSUInteger,JPAPIManagerErrorType){
   JPAPIManagerErrorTypeNeedAccessToken, // 需要重新刷新accessToken
   JPAPIManagerErrorTypeNeedLogin,       // 需要登陆
   JPAPIManagerErrorTypeDefault,         // 没有产生过API请求，这个是manager的默认状态。
   JPAPIManagerErrorTypeLoginCanceled,   // 调用API需要登陆态，弹出登陆页面之后用户取消登陆了
   JPAPIManagerErrorTypeSuccess,         // API请求成功且返回数据正确，此时manager的数据是可以直接拿来使用的。
   JPAPIManagerErrorTypeNoContent,       // API请求成功但返回数据不正确。如果回调数据验证函数返回值为NO，manager的状态就会是这个。
   JPAPIManagerErrorTypeParamsError,     // 参数错误，此时manager不会调用API，因为参数验证是在调用API之前做的。
   JPAPIManagerErrorTypeTimeout,         // 请求超时。CTAPIProxy设置的是20秒超时，具体超时时间的设置请自己去看CTAPIProxy的相关代码。
   JPAPIManagerErrorTypeNoNetWork,       // 网络不通。在调用API之前会判断一下当前网络是否通畅，这个也是在调用API之前验证的，和上面超时的状态是有区别的。
   JPAPIManagerErrorTypeCanceled,        // 取消请求
   JPAPIManagerErrorTypeNoError,         // 无错误
   JPAPIManagerErrorTypeDownGrade,       // APIManager被降级了
};

typedef NS_OPTIONS(NSUInteger,JPAPIManagerCachePolicy) {
   JPAPIManagerCachePolicyNoCache = 0,
   JPAPIManagerCachePolicyMemory = 1 << 0,
   JPAPIManagerCachePolicyDisk = 1 << 1,
};


extern NSString * _Nonnull const kJPAPIBaseManagerRequestID;

// notification name
extern NSString * _Nonnull const kJPUserTokenIllegalNotification;
extern NSString * _Nonnull const kJPUserTokenNotificationUserInfoKeyManagerToContinue;

// result
extern NSString * _Nonnull const kJPApiProxyValidateResultKeyResponseJSONObject;
extern NSString * _Nonnull const kJPApiProxyValidateResultKeyResponseJSONString;
extern NSString * _Nonnull const kJPApiProxyValidateResultKeyResponseData;

/*************************************************************************************/
@protocol JPAPIManager <NSObject>

@required
- (NSString *_Nonnull)methodName;
- (NSString *_Nonnull)serviceIdentifier;
- (JPAPIManagerRequestType)requestType;

@optional
- (void)cleanData;
- (NSDictionary *_Nullable)reformParams:(NSDictionary *_Nullable)params;
- (NSInteger)loadDataWithParams:(NSDictionary *_Nullable)params;

@end

/*************************************************************************************/
@protocol JPAPIManagerInterceptor <NSObject>

@optional
- (BOOL)manager:(JPAPIBaseManager *_Nonnull)manager beforePerformSuccessWithResponse:(JPURLResponse *_Nonnull)response;
- (void)manager:(JPAPIBaseManager *_Nonnull)manager afterPerformSuccessWithResponse:(JPURLResponse *_Nonnull)response;

- (BOOL)manager:(JPAPIBaseManager *_Nonnull)manager beforePerformFailWithResponse:(JPURLResponse *_Nonnull)response;
- (void)manager:(JPAPIBaseManager *_Nonnull)manager afterPerformFailWithResponse:(JPURLResponse *_Nonnull)response;

- (BOOL)manager:(JPAPIBaseManager *_Nonnull)manager shouldCallAPIWithParams:(NSDictionary *_Nullable)params;
- (void)manager:(JPAPIBaseManager *_Nonnull)manager afterCallingAPIWithParams:(NSDictionary *_Nullable)params;
- (void)manager:(JPAPIBaseManager *_Nonnull)manager didReceiveResponse:(JPURLResponse *_Nullable)response;

@end

/*************************************************************************************/

@protocol JPAPIManagerCallBackDelegate <NSObject>
@required

- (void)managerCallDLDLAPIDidSuccess:(JPAPIBaseManager * _Nonnull)manager;
- (void)managerCallDLDLAPIDidFailed:(JPAPIBaseManager * _Nonnull)manager;

@end

@protocol CTPagableAPIManager <NSObject>

@property (nonatomic, assign) NSInteger pageSize;
@property (nonatomic, assign, readonly) NSUInteger currentPageNumber;
@property (nonatomic, assign, readonly) BOOL isFirstPage;
@property (nonatomic, assign, readonly) BOOL isLastPage;

- (void)loadNextPage;

@end

/*************************************************************************************/

@protocol JPAPIManagerDataReformer <NSObject>
@required
- (id _Nullable)manager:(JPAPIBaseManager * _Nonnull)manager reformData:(NSDictionary * _Nullable)data;
@end

/*************************************************************************************/

@protocol JPAPIManagerValidator <NSObject>
@required
- (JPAPIManagerErrorType)manager:(JPAPIBaseManager *_Nonnull)manager isCorrectWithCallBackData:(NSDictionary *_Nullable)data;
- (JPAPIManagerErrorType)manager:(JPAPIBaseManager *_Nonnull)manager isCorrectWithParamsData:(NSDictionary *_Nullable)data;
@end

/*************************************************************************************/

@protocol JPAPIManagerParamSource <NSObject>
@required
- (NSDictionary *_Nullable)paramsForApi:(JPAPIBaseManager *_Nonnull)manager;
@end


//Tools
#define _JP_SINGLETON_DEF(_type_,_func_) + (_type_ *)_func_;+(instancetype) alloc __attribute__((unavailable("call sharedInstance instead")));+(instancetype) new __attribute__((unavailable("call sharedInstance instead")));-(instancetype) copy __attribute__((unavailable("call sharedInstance instead")));-(instancetype) mutableCopy __attribute__((unavailable("call sharedInstance instead")));
#define _JP_SINGLETON_IMP(_type_,_func_) + (_type_ *)_func_{static _type_ *theSharedInstance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{theSharedInstance = [[super alloc] init];});return theSharedInstance;}

#define JP_SINGLETON_DEF(_type_) _JP_SINGLETON_DEF(_type_,sharedInstance)
#define JP_SINGLETON_IMP(_type_) _JP_SINGLETON_IMP(_type_,sharedInstance)




#endif /* JPNetworkingDefines_h */
